package com.component.api.model.dto;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.component.api.excepiton.ComponentException;
import com.component.api.function.CompareFunction;
import com.component.api.model.UnifiedType;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

/**
 * 描述：
 * 野值规则列
 * @author xianggj
 * @Date 2021/11/29 14:09
 **/
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
public class OutliersColumnDTO extends ColumnDTO implements Serializable {
    private static final long serialVersionUID = -1L;
    /**
     * 过滤条件(==,＜,＞,≤,≥,!=,包含,不包含)
     *  前端过滤
     */
    private String filter;

    /**
     * 属性值
     */
    private String value;

    /**
     * 获取计算公式
     * @return
     */
    public CompareFunction getFunction(){
        if (StrUtil.isBlank(filter) || StrUtil.isBlank(value) ) {
            return (a,b) -> false;
        } else {

            return (a,b) ->{
                if (a == null || b == null){
                    return false;
                }
                switch (b){
                    case STRING:
                        return stringJudge(a);
                    case INTEGER:
                        return intJudge(a);
                    case LONG:
                        return longJudge(a);
                    case DOUBLE:
                        return doubleJudge(a);
                    case DATETIME:
                        return dateTimeJudge(a);
                    default:
                        return false;
                }

            };
        }
    }

    /**
     * 时间格式转换
     * @param oldVal 默认这个是通过toString 实现时间转换
     * @return
     */
    private boolean dateTimeJudge(Object oldVal){
        DateTime parse = null;
        if (oldVal instanceof  Date){
            parse = DateUtil.date((Date) oldVal);
        } else if (oldVal instanceof  LocalDateTime) {
            parse = new DateTime(((LocalDateTime)oldVal).atZone( ZoneId.systemDefault()).toInstant());
        } else  {
            throw new ComponentException("不支持该时间类型");
        }

        DateTime valueDate = DateUtil.parse(value);
        switch (filter){
            case "==":
                return DateUtil.compare(valueDate, parse) == 0;
            case "＜":
            case "<":
                return DateUtil.compare(valueDate, parse) == 1;
            case "＞":
            case ">":
                return DateUtil.compare(valueDate, parse) == -1;
            case "≤":
                return DateUtil.compare(valueDate, parse) != -1;
            case "≥":
                return DateUtil.compare(valueDate, parse) != 1;
            case "!=":
                return DateUtil.compare(valueDate, parse) != 0;
            default:
                return false;
        }
    }

    /**
     * 字符串转换
     * @param oldVal 默认这个是通过toString 实现时间转换
     * @return
     */
    private boolean stringJudge(Object oldVal){
        String oriVal = oldVal.toString();
        switch (filter){
            case "==":
                return StrUtil.equals(oriVal, value);
            case "＜":
            case "<":
                return StrUtil.compare(oriVal, value, true) == -1;
            case "＞":
            case ">":
                return StrUtil.compare(oriVal, value, true) == 1;
            case "≤":
                return StrUtil.compare(oriVal, value, true) != 1;
            case "≥":
                return StrUtil.compare(oriVal, value, true) != -1;
            case "!=":
                return !StrUtil.equals(oriVal, value);
            case "包含":
                return StrUtil.contains(oriVal, value);
            case "不包含":
                return !StrUtil.contains(oriVal, value);
            default:
                return false;
        }
    }

    /**
     * int转换
     * @param oldVal 默认这个是通过toString 实现时间转换
     * @return
     */
    private boolean intJudge(Object oldVal){
        Integer intVal = Integer.valueOf(oldVal.toString());
        Integer val = Integer.valueOf(value);
        switch (filter){
            case "==":
                return intVal.equals(val);
            case "＜":
            case "<":
                return intVal < val;
            case "＞":
            case ">":
                return intVal > val;
            case "≤":
                return intVal <= val;
            case "≥":
                return intVal >= val;
            case "!=":
                return !intVal.equals(val);
            default:
                return false;
        }
    }
    /**
     * double转换
     * @param oldVal 默认这个是通过toString 实现时间转换
     * @return
     */
    private boolean doubleJudge(Object oldVal){
        Double douVal = Double.valueOf(oldVal.toString());
        Double val = Double.valueOf(value);
        switch (filter){
            case "==":
                return douVal.equals(val);
            case "＜":
            case "<":
                return douVal < val;
            case "＞":
            case ">":
                return douVal > val;
            case "≤":
                return douVal <= val;
            case "≥":
                return douVal >= val;
            case "!=":
                return !douVal.equals(val);
            default:
                return false;
        }
    }
    /**
     * long转换
     * @param oldVal 默认这个是通过toString 实现时间转换
     * @return
     */
    private boolean longJudge(Object oldVal){
        Long longVal = Long.valueOf(oldVal.toString());
        Long val = Long.valueOf(value);
        switch (filter){
            case "==":
                return longVal.equals(val);
            case "＜":
            case "<":
                return longVal < val;
            case "＞":
            case ">":
                return longVal > val;
            case "≤":
                return longVal <= val;
            case "≥":
                return longVal >= val;
            case "!=":
                return !longVal.equals(val);
            default:
                return false;
        }
    }
}
